package generate

import (
	"bytes"
	"context"
	"fmt"

	"github.com/gin-admin/gin-admin-cli/v5/util"
)

func getBllImplFileName(dir, name string) string {
	fullname := fmt.Sprintf("%s/internal/app/service/%s.srv.go", dir, util.ToLowerUnderlinedNamer(name))
	return fullname
}

// 生成bll实现文件
func genBllImpl(ctx context.Context, pkgName, dir, name, comment string, fields ...schemaField) error {
	fmt.Println(name)
	bufItem := new(bytes.Buffer)
	for _, field := range fields {
		//Name: item.Name,
		bufItem.WriteString(fmt.Sprintf("%s: item.%s, \n", field.Name, field.Name))
	}
	fmt.Println(bufItem.String())
	InitialData := map[string]interface{}{
		"PkgName":  pkgName,
		"Name":     name,
		"Comment":  comment,
		"InitData": nil,
		"bufItem":  bufItem,
	}

	InitData, err := execParseTpl(serviceInitImplTpl, InitialData)
	if err != nil {
		return err
	}
	InitDataImport, err := execParseTpl(serviceInitImportImplTpl, InitialData)
	if err != nil {
		return err
	}
	// fmt.Println(InitData)
	// return nil

	data := map[string]interface{}{
		"PkgName":        pkgName,
		"Name":           name,
		"Comment":        comment,
		"InitData":       InitData,
		"InitDataImport": InitDataImport,
	}

	buf, err := execParseTpl(serviceImplTpl, data)
	if err != nil {
		return err
	}

	fullname := getBllImplFileName(dir, name)
	err = createFile(ctx, fullname, buf)
	if err != nil {
		return err
	}

	fmt.Printf("File write success: %s\n", fullname)

	return execGoFmt(fullname)
}

const serviceInitImportImplTpl = `
	"fmt"
	"os"
	"encoding/json"
	"github.com/LyricTian/gin-admin/v8/pkg/util/yaml"
`
const serviceInitImplTpl = `

type {{.Name}}Schema []*schema.{{.Name}}

// InitData 初始化菜单数据
func (a *{{.Name}}Srv) InitData(ctx context.Context, dataFile string) error {
	fmt.Println(dataFile)

	result, err := a.{{.Name}}Repo.Query(ctx, schema.{{.Name}}QueryParam{
		PaginationParam: schema.PaginationParam{OnlyCount: true},
	})
	if err != nil {
		return err
	} else if result.PageResult.Total > 0 {
		// 如果存在则不进行初始化
		return nil
	}
	// var data {{.Name}}Schema
	data, err := a.readData(dataFile)

	// res, _ := json.Marshal(data)
	// fmt.Printf("%s", res)

	if err != nil {
		return err
	}
	return a.create{{.Name}}s(ctx, data)

}

func (a *{{.Name}}Srv) readData(name string) ({{.Name}}Schema, error) {
	var data {{.Name}}Schema
	file, err := os.Open(name)
	if err != nil {
		return data, err
	}
	defer file.Close()
	// d := util.YAMLNewDecoder(file)
	d := yaml.NewDecoder(file)
	d.SetStrict(true)
	err = d.Decode(&data)
	return data, err
}

func (a *{{.Name}}Srv) create{{.Name}}s(ctx context.Context, list {{.Name}}Schema) error {

	err := a.TransRepo.Exec(ctx, func(ctx context.Context) error {
		for _, item := range list {
			sitem := schema.{{.Name}}{
				{{.bufItem}}
			}
			fmt.Println("1111")

			_, err := a.Create(ctx, sitem)
			if err != nil {
				fmt.Println(err)

				return err
			}
			res, _ := json.Marshal(sitem)
			fmt.Printf("%s", res)

		}

		res, _ := json.Marshal(list)
		fmt.Printf("%s", res)

		return nil

	})
	if err != nil {
		return nil
	}
	// return schema.NewIDResult(item.ID), nil
	return nil
}

`

const serviceImplTpl = `
package service

import (
	"context"
	{{.InitDataImport}}
	"github.com/google/wire"

	"{{.PkgName}}/internal/app/dao"
	"{{.PkgName}}/internal/app/schema"
	"{{.PkgName}}/pkg/errors"
	"{{.PkgName}}/pkg/util/snowflake"
)

var {{.Name}}Set = wire.NewSet(wire.Struct(new({{.Name}}Srv), "*"))

type {{.Name}}Srv struct {
	TransRepo              		*dao.TransRepo
	{{.Name}}Repo               *dao.{{.Name}}Repo
}

{{.InitData}}

func (a *{{.Name}}Srv) Query(ctx context.Context, params schema.{{.Name}}QueryParam, opts ...schema.{{.Name}}QueryOptions) (*schema.{{.Name}}QueryResult, error) {
	result, err := a.{{.Name}}Repo.Query(ctx, params, opts...)
	if err != nil {
		return nil, err
	}
	return result, nil
}

func (a *{{.Name}}Srv) Get(ctx context.Context, id uint64, opts ...schema.{{.Name}}QueryOptions) (*schema.{{.Name}}, error) {
	item, err := a.{{.Name}}Repo.Get(ctx, id, opts...)
	if err != nil {
		return nil, err
	} else if item == nil {
		return nil, errors.ErrNotFound
	}

	return item, nil
}

func (a *{{.Name}}Srv) Create(ctx context.Context, item schema.{{.Name}}) (*schema.IDResult, error) {
	item.ID = snowflake.MustID()

	err := a.TransRepo.Exec(ctx, func(ctx context.Context) error {
		return a.{{.Name}}Repo.Create(ctx, item)
	})
	if err != nil {
		return nil, err
	}

	return schema.NewIDResult(item.ID), nil
}

func (a *{{.Name}}Srv) Update(ctx context.Context, id uint64, item schema.{{.Name}}) error {
	oldItem, err := a.Get(ctx, id)
	if err != nil {
		return err
	} else if oldItem == nil {
		return errors.ErrNotFound
	}

	item.ID = oldItem.ID
	item.Creator = oldItem.Creator
	item.CreatedAt = oldItem.CreatedAt

	return a.TransRepo.Exec(ctx, func(ctx context.Context) error {
		return a.{{.Name}}Repo.Update(ctx, id, item)
	})
}

func (a *{{.Name}}Srv) Delete(ctx context.Context, id uint64) error {
	oldItem, err := a.{{.Name}}Repo.Get(ctx, id)
	if err != nil {
		return err
	} else if oldItem == nil {
		return errors.ErrNotFound
	}

	return a.TransRepo.Exec(ctx, func(ctx context.Context) error {
		return a.{{.Name}}Repo.Delete(ctx, id)
	})
}

func (a *{{.Name}}Srv) UpdateStatus(ctx context.Context, id uint64, status int) error {
	oldItem, err := a.{{.Name}}Repo.Get(ctx, id)
	if err != nil {
		return err
	} else if oldItem == nil {
		return errors.ErrNotFound
	} else if oldItem.Status == status {
		return nil
	}

	return a.{{.Name}}Repo.UpdateStatus(ctx, id, status)
}

`
